﻿using System;
using System.Collections.Generic;
using System.Text;
using TTEngine;

namespace TTEditor
{

    public class AssetMetaData
    {
        public AssetHead head;
        public Dictionary<string, byte[]> assetDatas;

        public void Open(string filename)
        {
            head = new AssetHead();
            assetDatas = new Dictionary<string, byte[]>();
            if (System.IO.File.Exists(filename) == false)
            {
                head.MagicHead = "TTA";
                head.version = 1;
            }
            else
            {
                try
                {
                    using (var fs = System.IO.File.OpenRead(filename))
                    {
                        AssetDataTool.ReadAssetHead(fs, head);
                        for (var i = 0; i < head.AssetDataInfo.Length; i++)
                        {
                            var hash = head.AssetDataInfo[i].GetHashStr();
                            if (assetDatas.ContainsKey(hash) == false)
                            {
                                var data = new byte[head.AssetDataInfo[i].length];
                                fs.Seek(head.AssetDataInfo[i].dataOffset, System.IO.SeekOrigin.Begin);
                                fs.Read(data, 0, data.Length);
                                assetDatas[hash] = data;
                            }
                        }
                    }
                }
                catch (Exception err)
                {
                    throw new Exception("meta文件损坏/bad meta file:" + filename, err);
                }
            }
        }
        public void AddPlatformData(AssetPlatform platform, byte[] data)
        {
            AssetDataInfo info = AssetDataTool.ComputeAssetDataInfo(data, platform, 0);
            assetDatas[info.GetHashStr()] = data;

            //替换
            if (head.AssetDataInfo != null)
            {
                for (var i = 0; i < head.AssetDataInfo.Length; i++)
                {
                    if (head.AssetDataInfo[i].platform == platform)
                    {
                        head.AssetDataInfo[i] = info;
                        assetDatas[head.AssetDataInfo[i].GetHashStr()] = data;
                        return;
                    }
                }
            }

            //新增
            {
                var list = head.AssetDataInfo == null ? new List<AssetDataInfo>() : new List<AssetDataInfo>(head.AssetDataInfo);
                list.Add(info);
                head.AssetDataInfo = list.ToArray();
            }
        }

        private void UpdateOffset()
        {
            if (head.AssetDataInfo.Length != assetDatas.Count)
                throw new Exception("error head.AssetDataInfo.Length!=assetDatas.Count");
            uint Offset = (uint)head.ComputeLength();
            Dictionary<string, uint> mapAssetOffset = new Dictionary<string, uint>();

            for (var i = 0; i < head.AssetDataInfo.Length; i++)
            {
                var hash = head.AssetDataInfo[i].GetHashStr();
                var data = assetDatas[hash];
                if (head.AssetDataInfo[i].length != data.Length)
                {
                    throw new Exception("error head.AssetDataInfo[i].length!=data.Length " + hash + "p=" + head.AssetDataInfo[i].platform);
                }
                if (mapAssetOffset.ContainsKey(hash) == false)
                {
                    mapAssetOffset[hash] = Offset;
                    Offset += (uint)data.Length;
                }
                head.AssetDataInfo[i].dataOffset = mapAssetOffset[hash];

            }
        }
        public void Save(string filename)
        {
            UpdateOffset();
            System.IO.File.Delete(filename);
            List<string> saveHashes = new List<string>();
            using (var fs = System.IO.File.OpenWrite(filename))
            {
                AssetDataTool.WriteAssetHead(fs, head);
                for (var i = 0; i < head.AssetDataInfo.Length; i++)
                {
                    var hash = head.AssetDataInfo[i].GetHashStr();
                    if (!saveHashes.Contains(hash))
                    {
                        fs.Seek(head.AssetDataInfo[i].dataOffset, System.IO.SeekOrigin.Begin);
                        var data = assetDatas[hash];
                        fs.Write(data, 0, data.Length);
                        saveHashes.Add(head.AssetDataInfo[i].GetHashStr());
                    }
                }
            }
        }
    }
}
